<?php

namespace App\Jobs;

use App\Logging\Service\LogJobService;
use App\Models\FailedJobs;
use App\Services\ExceptionService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

abstract class BaseJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /* @var string 名称 */
    protected $name = '';
    /* @var string 描述 */
    protected $description = '';
    /* @var bool 是否需要异常通知，部分情况不需要，比如：异常通知队列 */
    protected $needExceptionNotify = true;

    protected $uuid = '';
    /**
     * @var int 最大重试次数
     */
    public $tries = 1;
    public $timeout = 1800;

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $this->uuid = $this->job->payload()['uuid'];

        $this->initLog();

        if (!$this->needExceptionNotify) {
            ExceptionService::getInstance()->closeExceptionNotify();
        }

        Log::Info("job[{$this->name}]开始");

        $this->handleExec();

        Log::Info("job[{$this->name}]结束");
    }

    private function initLog()
    {
        // 设置指定通道需要的参数
        LogJobService::getInstance()
            ->setJobName($this->name)
            ->setJobUuid($this->uuid)
            ->setJobClass(static::class);

        // 设置默认的日志驱动为
        /* @var $logManager \Illuminate\Log\LogManager */
        $logManager = Log::getFacadeRoot();
        $logManager->setDefaultDriver('job');
    }

    abstract protected function handleExec();

    /**
     * 这里如果再报错会走全局异常，全局异常会把异常再推送到队列，导致死循环
     * @param \Throwable $e
     * @author Chris Yu <chrisyu@crabapple.top> 2024/11/12
     */
    public function failed(\Throwable $e)
    {
        // 记录异常。异常信息尽量不要计入 trace 等比较长的，会在全局处理中再记录 trace 了
        Log::error("job[{$this->name}]处理异常：" . $e->getMessage(),
            [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTrace()
            ]
        );
    }
}
